home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / common / arch.c next >
C/C++ Source or Header  |  1996-07-24  |  11KB  |  432 lines

  1. /*
  2.  * static char *rcsid_arch_c =
  3.  *   "$Id: arch.c,v 1.23 1996/01/02 10:25:28 master Exp $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to frankj@ifi.uio.no.
  26. */
  27.  
  28. #include <global.h>
  29. #include <arch.h>
  30. #include <funcpoint.h>
  31.  
  32. static archetype *arch_table[ARCHTABLE];
  33. int arch_cmp=0;        /* How many strcmp's */
  34. int arch_search=0;    /* How many searches */
  35. int arch_init;        /* True if doing arch initialization */
  36. /*
  37.  * Initialises the internal linked list of archetypes (read from file).
  38.  * Then the global "empty_archetype" pointer is initialised.
  39.  * Then the blocksview[] array is initialised.
  40.  */
  41.  
  42. void init_archetypes() { /* called from add_player() and edit() */
  43.   if(first_archetype!=NULL) /* Only do this once */
  44.     return;
  45.   arch_init = 1;
  46.   load_archetypes();
  47.   arch_init = 0;
  48.   empty_archetype=find_archetype("empty_archetype");
  49. /*  init_blocksview();*/
  50. }
  51.  
  52. /*
  53.  * Stores debug-information about how efficient the hashtable
  54.  * used for archetypes has been in the static errmsg array.
  55.  */
  56.  
  57. void arch_info(object *op) {
  58.   sprintf(errmsg,"%d searches and %d strcmp()'s",arch_search,arch_cmp);
  59.   (*draw_info_func)(NDI_BLACK, 0, op,errmsg);
  60. }
  61.  
  62. /*
  63.  * Initialise the hashtable used by the archetypes.
  64.  */
  65.  
  66. void clear_archetable() {
  67.   memset((void *) arch_table,0,ARCHTABLE*sizeof(archetype *));
  68. }
  69.  
  70. /*
  71.  * An alternative way to init the hashtable which is slower, but _works_...
  72.  */
  73.  
  74. void init_archetable() {
  75.   archetype *at;
  76.   LOG(llevDebug,"Setting up archetable...");
  77.   for(at=first_archetype;at!=NULL;at=(at->more==NULL)?at->next:at->more)
  78.     add_arch(at);
  79.   LOG(llevDebug,"done\n");
  80. }
  81.  
  82. /*
  83.  * Dumps an archetype to debug-level output.
  84.  */
  85.  
  86. void dump_arch(archetype *at) {
  87.   unsigned char i;
  88.   dump_object(&at->clone);
  89.   LOG(llevDebug,"Arch: %s [%d] = %s\n",at->name,at->animations,errmsg);
  90.   for(i=0; i < (int)at->animations; i++)
  91.     LOG(llevDebug,"Anim %d=%d\n",i,at->faces[i]);
  92. }
  93.  
  94. /*
  95.  * Dumps _all_ archetypes to debug-level output.
  96.  * If you run crossfire with debug, and enter DM-mode, you can trigger
  97.  * this with the O key.
  98.  */
  99.  
  100. void dump_all_archetypes() {
  101.   archetype *at;
  102.   for(at=first_archetype;at!=NULL;at=(at->more==NULL)?at->next:at->more)
  103.     dump_arch(at);
  104. }
  105.  
  106. /*
  107.  * Allocates, initialises and returns the pointer to an archetype structure.
  108.  */
  109.  
  110. archetype *get_archetype_struct() {
  111.   archetype *new;
  112.  
  113.   new=(archetype *)CALLOC(1,sizeof(archetype));
  114.   if(new==NULL)
  115.     fatal(OUT_OF_MEMORY);
  116.   new->faces=NULL;
  117.   new->next=NULL;
  118.   new->name=NULL;
  119.   new->randomitems=NULL;
  120.   new->clone.other_arch=NULL;
  121.   new->clone.name=NULL;
  122.   new->clone.title=NULL;
  123.   new->clone.race=NULL;
  124.   new->clone.slaying=NULL;
  125.   new->clone.msg=NULL;
  126.   clear_object(&new->clone);  /* to initial state other also */
  127.   CLEAR_FLAG((&new->clone),FLAG_FREED); /* This shouldn't matter, since copy_object() */
  128.   SET_FLAG((&new->clone), FLAG_REMOVED); /* doesn't copy these flags... */
  129.   new->head=NULL;
  130.   new->more=NULL;
  131.   new->animations=0;
  132.   return new;
  133. }
  134.  
  135. /*
  136.  * Reads/parses the archetype-file, and copies into a linked list
  137.  * of archetype-structures.
  138.  */
  139. void first_arch_pass(FILE *fp) {
  140.   object *op;
  141.   archetype *at,*prev=NULL,*last_more=NULL;
  142.   int i;
  143.  
  144.   op=get_object();
  145.   op->arch=first_archetype=at=get_archetype_struct();
  146.   while((i=load_object(fp,op))) {
  147.     copy_object(op,&at->clone);
  148.     at->clone.speed_left= -0.1;
  149.     switch(i) {
  150.     case 1: /* A new archetype, just link it with the previous */
  151.       if(last_more!=NULL)
  152.         last_more->next=at;
  153.       if(prev!=NULL)
  154.         prev->next=at;
  155.       prev=last_more=at;
  156.       break;
  157.     case 2:
  158.       LOG(llevError,"Error: Archetype with inventory is illegal!\n");
  159.       exit(-1);
  160.     case 3: /* Another part of the previous archetype, link it correctly */
  161.       at->head=prev;
  162.       at->clone.head = &prev->clone;
  163.       if(last_more!=NULL) {
  164.         last_more->more=at;
  165.         last_more->clone.more = &at->clone;
  166.       }
  167.       last_more=at;
  168.       break;
  169.     }
  170.     at=get_archetype_struct();
  171.     clear_object(op);
  172.     op->arch=at;
  173.   }
  174.   free_object(op);
  175. }
  176.  
  177. /*
  178.  * Reads the archetype file once more, and links all pointers between
  179.  * archetypes.
  180.  */
  181.  
  182. void second_arch_pass(FILE *fp) {
  183.   char buf[MAX_BUF],*variable=buf,*argument,*cp;
  184.   archetype *at=NULL,*other;
  185.  
  186.   while(fgets(buf,MAX_BUF,fp)!=NULL) {
  187.     if(*buf=='#')
  188.       continue;
  189.     if((argument=strchr(buf,' '))!=NULL) {
  190.       *argument='\0',argument++;
  191.       if((cp=strchr(argument,'\n'))!=NULL)
  192.         *cp='\0';
  193.     }
  194.     if(!strcmp("Object",variable)) {
  195.       if((at=find_archetype(argument))==NULL)
  196.         LOG(llevError,"Warning: failed to find arch %s\n",argument);
  197.     } else if(!strcmp("other_arch",variable)) {
  198.       if(at!=NULL&&at->clone.other_arch==NULL) {
  199.         if((other=find_archetype(argument))==NULL)
  200.           LOG(llevError,"Warning: failed to find other_arch %s\n",argument);
  201.         else if(at!=NULL)
  202.           at->clone.other_arch=other;
  203.       }
  204.     } else if(!strcmp("randomitems",variable)) {
  205.       if(at!=NULL) {
  206.         treasurelist *tl=find_treasurelist(argument);
  207.         if(tl==NULL)
  208.           LOG(llevError,"Failed to link treasure to arch: %s\n",variable);
  209.         else
  210.           at->randomitems=tl;
  211.       }
  212.     }
  213.   }
  214. }
  215.  
  216. #ifdef DEBUG
  217. void check_generators() {
  218.   archetype *at;
  219.   for(at=first_archetype;at!=NULL;at=at->next)
  220.     if(QUERY_FLAG(&at->clone,FLAG_GENERATOR)&&at->clone.other_arch==NULL)
  221.       LOG(llevError,"Warning: %s is generator but lacks other_arch.\n",
  222.               at->name);
  223. }
  224. #endif
  225.  
  226. /*
  227.  * First initialises the archtype hash-table (init_archetable()).
  228.  * Reads and parses the archetype file (with the first and second-pass
  229.  * functions).
  230.  * Then initialises treasures by calling load_treasures().
  231.  */
  232.  
  233. void load_archetypes() {
  234.   FILE *fp;
  235.   char filename[MAX_BUF];
  236.   int comp;
  237.  
  238.   sprintf(filename,"%s/%s",LibDir,ArcheTypes);
  239.   if((fp=open_and_uncompress(filename,0,&comp))==NULL) {
  240.     LOG(llevError,"Can't open archetype file.\n");
  241.     return;
  242.   }
  243.   /*setlinebuf (fp);*/
  244.   clear_archetable();
  245.   LOG(llevDebug,"arch-pass 1...");
  246.   first_arch_pass(fp);
  247.   LOG(llevDebug,"done\n");
  248.   init_archetable();
  249.   warn_archetypes=1;
  250.   rewind(fp);
  251.   LOG(llevDebug,"loading treasure...");
  252.   load_treasures();
  253.   LOG(llevDebug,"done\narch-pass 2...");
  254.   second_arch_pass(fp);
  255.   LOG(llevDebug,"done\n");
  256. #ifdef DEBUG
  257.   check_generators();
  258. #endif
  259.   close_and_delete(fp, comp);
  260. }
  261.  
  262. /*
  263.  * Creates and returns a new object which is a copy of the given archetype.
  264.  * This function returns NULL on failure.
  265.  */
  266.  
  267. object *arch_to_object(archetype *at) {
  268.   object *op;
  269.   if(at==NULL) {
  270.     if(warn_archetypes)
  271.       LOG(llevError,"Couldn't find archetype.\n");
  272.     return NULL;
  273.   }
  274.   op=get_object();
  275.   copy_object(&at->clone,op);
  276.   op->arch=at;
  277.   return op;
  278. }
  279.  
  280. /*
  281.  * Creates an object.  This function is called by get_archetype()
  282.  * if it fails to find the appropriate archetype.
  283.  * Thus get_archetype() will be guaranteed to always return
  284.  * an object, and never NULL.
  285.  */
  286.  
  287. object *create_singularity(char *name) {
  288.   object *op;
  289.   char buf[MAX_BUF];
  290.   sprintf(buf,"singluarity (%s)",name);
  291.   op = get_object();
  292.   op->name = add_string(buf);
  293.   SET_FLAG(op,FLAG_NO_PICK);
  294.   return op;
  295. }
  296.  
  297. /*
  298.  * Finds which archetype matches the given name, and returns a new
  299.  * object containing a copy of the archetype.
  300.  */
  301.  
  302. object *get_archetype(char *name) {
  303.   archetype *at;
  304.   at = find_archetype(name);
  305.   if (at == NULL)
  306.     return create_singularity(name);
  307.   return arch_to_object(at);
  308. }
  309.  
  310. /*
  311.  * Hash-function used by the arch-hashtable.
  312.  */
  313.  
  314. unsigned long
  315. hasharch(char *str, int tablesize) {
  316.     unsigned long hash = 0;
  317.     int i = 0, rot = 0;
  318.     char *p;
  319.  
  320.     for (p = str; i < MAXSTRING && *p; p++, i++) {
  321.         hash ^= (unsigned long) *p << rot;
  322.         rot += 2;
  323.         if (rot >= (sizeof(long) - sizeof(char)) * 8)
  324.             rot = 0;
  325.     }
  326.     return (hash % tablesize);
  327. }
  328.  
  329. /*
  330.  * Finds, using the hashtable, which archetype matches the given name.
  331.  * returns a pointer to the found archetype, otherwise NULL.
  332.  */
  333.  
  334. archetype *find_archetype(char *name) {
  335.   archetype *at;
  336.   unsigned long index;
  337.  
  338.   if (name == NULL)
  339.     return (archetype *) NULL;
  340.  
  341.   index=hasharch(name, ARCHTABLE);
  342.   arch_search++;
  343.   for(;;) {
  344.     at = arch_table[index];
  345.     if (at==NULL) {
  346.       if(warn_archetypes)
  347.         LOG(llevError,"Couldn't find archetype %s\n",name);
  348.       return NULL;
  349.     }
  350.     arch_cmp++;
  351.     if (!strcmp(at->name,name))
  352.       return at;
  353.     if(++index>=ARCHTABLE)
  354.       index=0;
  355.   }
  356. }
  357.  
  358. /*
  359.  * Adds an archetype to the hashtable.
  360.  */
  361.  
  362. void add_arch(archetype *at) {
  363.   int index=hasharch(at->name, ARCHTABLE),org_index=index;
  364.   for(;;) {
  365.     if(arch_table[index]==NULL) {
  366.       arch_table[index]=at;
  367.       return;
  368.     }
  369.     if(++index==ARCHTABLE)
  370.       index=0;
  371.     if(index==org_index)
  372.       fatal(ARCHTABLE_TOO_SMALL);
  373.   }
  374. }
  375.  
  376. /*
  377.  * Returns the first archetype using the given type.
  378.  * Used in treasure-generation.
  379.  */
  380.  
  381. archetype *type_to_archetype(int type) {
  382.   archetype *at;
  383.  
  384.   for(at=first_archetype;at!=NULL;at=(at->more==NULL)?at->next:at->more)
  385.     if(at->clone.type==type)
  386.       return at;
  387.   return NULL;
  388. }
  389.  
  390. /*
  391.  * Returns a new object copied from the first archetype matching
  392.  * the given type.
  393.  * Used in treasure-generation.
  394.  */
  395.  
  396. object *clone_arch(int type) {
  397.   archetype *at;
  398.   object *op=get_object();
  399.  
  400.   if((at=type_to_archetype(type))==NULL) {
  401.     LOG(llevError,"Can't clone archetype %d\n",type);
  402.     free_object(op);
  403.     return NULL;
  404.   }
  405.   copy_object(&at->clone,op);
  406.   return op;
  407. }
  408.  
  409. /*
  410.  * member: make instance from class
  411.  */
  412.  
  413. object *ObjectCreateArch (archetype * at)
  414. {
  415.     object *op, *prev = NULL, *head = NULL;
  416.  
  417.     while (at) {
  418.         op = arch_to_object (at);
  419.         op->x = at->clone.x;
  420.         op->y = at->clone.y;
  421.         if (head)
  422.             op->head = head, prev->more = op;
  423.         if (!head)
  424.             head = op;
  425.         prev = op;
  426.         at = at->more;
  427.     }
  428.     return (head);
  429. }
  430.  
  431. /*** end of arch.c ***/
  432.